package com.bijava.files.controller;

import com.bijava.files.configure.FileProperties;
import com.bijava.files.utils.FileUtils;
import io.swagger.annotations.Api;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.tika.Tika;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

@CrossOrigin
@Controller
@Api(tags = "文件接口管理")
@RequestMapping("/api")
public class ApiController {
    @Autowired
    private FileProperties properties;

    /**
     * 上传文件
     */
    @ResponseBody
    @PostMapping("/file/upload")
    public Map upload(@RequestParam MultipartFile file) {
        String root = properties.getRoot();
        Boolean rename = properties.getUuidName();
        Boolean thumbnail = properties.getUseSm();

        //文件原始名称
        String originalFileName = file.getOriginalFilename();
        String suffix = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);
        String prefix = originalFileName.substring(0, originalFileName.lastIndexOf("."));
        // 保存到磁盘
        File outFile;
        String path;
        if (rename != null && rename) {
            path = FileUtils.getDate() + FileUtils.getUUID() + "." + suffix;
            outFile = new File(File.listRoots()[0], root + path);
        } else {
            int index = 1;
            path = FileUtils.getDate() + originalFileName;
            outFile = new File(File.listRoots()[0], root + path);
            while (outFile.exists()) {
                path = FileUtils.getDate() + prefix + "(" + index + ")." + suffix;
                outFile = new File(File.listRoots()[0], root + path);
                index++;
            }
        }
        try {
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            file.transferTo(outFile);
            Map rs = FileUtils.getRS(200, "上传成功", path);
            //生成缩略图
            if (thumbnail != null && thumbnail) {
                // 获取文件类型
                String contentType = null;
                try {
                    contentType = new Tika().detect(outFile);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (contentType != null && contentType.startsWith("image/")) {
                    File smImg = new File(File.listRoots()[0], root + "sm/" + path);
                    if (!smImg.getParentFile().exists()) {
                        smImg.getParentFile().mkdirs();
                    }
                    Thumbnails.of(outFile).scale(1f).outputQuality(0.25f).toFile(smImg);
                    rs.put("smUrl", "sm/" + path);
                }
            }
            return rs;
        } catch (Exception e) {
            e.printStackTrace();
            return FileUtils.getRS(500, e.getMessage());
        }
    }

    /**
     * 查看原文件
     */
    @GetMapping("/file/{year}/{month}/{day}/{file:.+}")
    public String file(@PathVariable("year") String year, @PathVariable("month") String month,
                       @PathVariable("day") String day, @PathVariable("file") String fileName, HttpServletResponse response) {
        String root = properties.getRoot();
        Boolean useNginx = properties.getUseNginx();
        String nginxUrl = properties.getNginxUrl();

        String filePath = year + "/" + month + "/" + day + "/" + fileName;
        if (useNginx) {
            if (nginxUrl == null) {
                nginxUrl = "/";
            }
            if (!nginxUrl.endsWith("/")) {
                nginxUrl += "/";
            }
            String newName;
            try {
                newName = URLEncoder.encode(filePath, "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                newName = filePath;
            }
            return "redirect:" + nginxUrl + newName;
        }
        if (root == null) {
            root = "/";
        }
        if (!root.endsWith("/")) {
            root += "/";
        }
        FileUtils.outputFile(root + filePath, response);
        return null;
    }

    /**
     * 查看缩略图
     */
    @GetMapping("/file/sm/{year}/{month}/{day}/{file:.+}")
    public String fileSm(@PathVariable("year") String year, @PathVariable("month") String month,
                         @PathVariable("day") String day, @PathVariable("file") String fileName, HttpServletResponse response) {
        String root = properties.getRoot();
        Boolean useNginx = properties.getUseNginx();
        String nginxUrl = properties.getNginxUrl();
        String filePath = "sm/" + year + "/" + month + "/" + day + "/" + fileName;
        if (useNginx) {
            if (nginxUrl == null) {
                nginxUrl = "/";
            }
            if (!nginxUrl.endsWith("/")) {
                nginxUrl += "/";
            }
            String newName;
            try {
                newName = URLEncoder.encode(filePath, "utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                newName = filePath;
            }
            return "redirect:" + nginxUrl + newName;
        }
        if (root == null) {
            root = "/";
        }
        if (!root.endsWith("/")) {
            root += "/";
        }
        FileUtils.outputFile(root + filePath, response);
        return null;
    }

    /**
     * 获取全部文件
     */
    @ResponseBody
    @RequestMapping("/file/list")
    public Map list(String dir, String accept, String exts) {
        String root = properties.getRoot();
        String[] mExts = null;
        if (exts != null && !exts.trim().isEmpty()) {
            mExts = exts.split(",");
        }
        if (root == null) {
            root = "/";
        }
        if (!root.endsWith("/")) {
            root += "/";
        }
        Map<String, Object> rs = new HashMap<>();
        if (dir == null || "/".equals(dir)) {
            dir = "";
        } else if (dir.startsWith("/")) {
            dir = dir.substring(1);
        }
        File file = new File(File.listRoots()[0], root + dir);
        File[] listFiles = file.listFiles();
        List<Map> dataList = new ArrayList<>();
        if (listFiles != null) {
            for (File f : listFiles) {
                if ("sm".equals(f.getName())) {
                    continue;
                }
                Map<String, Object> m = new HashMap<>();
                m.put("name", f.getName());  // 文件名称
                m.put("updateTime", f.lastModified());  // 修改时间
                m.put("isDir", f.isDirectory());  // 是否是目录
                if (f.isDirectory()) {
                    m.put("type", "dir");  // 文件类型
                } else {
                    String type;
                    m.put("url", (dir.isEmpty() ? dir : (dir + "/")) + f.getName());  // 文件地址
                    // 获取文件类型
                    String contentType = null;
                    String suffix = f.getName().substring(f.getName().lastIndexOf(".") + 1);
                    try {
                        // Path path = Paths.get(f.getName());
                        // contentType = Files.probeContentType(path);
                        contentType = new Tika().detect(f);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    // 筛选文件类型
                    if (accept != null && !accept.trim().isEmpty() && !accept.equals("file")) {
                        if (contentType == null || !contentType.startsWith(accept + "/")) {
                            continue;
                        }
                        if (mExts != null) {
                            for (String ext : mExts) {
                                if (!f.getName().endsWith("." + ext)) {
                                    continue;
                                }
                            }
                        }
                    }
                    // 获取文件图标
                    if ("ppt".equalsIgnoreCase(suffix) || "pptx".equalsIgnoreCase(suffix)) {
                        type = "ppt";
                    } else if ("doc".equalsIgnoreCase(suffix) || "docx".equalsIgnoreCase(suffix)) {
                        type = "doc";
                    } else if ("xls".equalsIgnoreCase(suffix) || "xlsx".equalsIgnoreCase(suffix)) {
                        type = "xls";
                    } else if ("pdf".equalsIgnoreCase(suffix)) {
                        type = "pdf";
                    } else if ("html".equalsIgnoreCase(suffix) || "htm".equalsIgnoreCase(suffix)) {
                        type = "htm";
                    } else if ("txt".equalsIgnoreCase(suffix)) {
                        type = "txt";
                    } else if ("swf".equalsIgnoreCase(suffix)) {
                        type = "flash";
                    } else if ("zip".equalsIgnoreCase(suffix) || "rar".equalsIgnoreCase(suffix) || "7z".equalsIgnoreCase(suffix)) {
                        type = "zip";
                    } else if (contentType != null && contentType.startsWith("audio/")) {
                        type = "mp3";
                    } else if (contentType != null && contentType.startsWith("video/")) {
                        type = "mp4";
                    } else if (contentType != null && contentType.startsWith("image/")) {
                        type = "png";
                    } else {
                        type = "file";
                    }
                    m.put("type", type);
                    // 是否有缩略图
                    String smUrl = "sm/" + (dir.isEmpty() ? dir : (dir + "/")) + f.getName();
                    if (new File(File.listRoots()[0], root + smUrl).exists()) {
                        m.put("hasSm", true);
                        m.put("smUrl", smUrl);  // 缩略图地址
                    }
                }
                dataList.add(m);
            }
        }
        // 根据上传时间排序
        Collections.sort(dataList, (o1, o2) -> {
            Long l1 = (long) o1.get("updateTime");
            Long l2 = (long) o2.get("updateTime");
            return l1.compareTo(l2);
        });
        // 把文件夹排在前面
        Collections.sort(dataList, (o1, o2) -> {
            Boolean l1 = (boolean) o1.get("isDir");
            Boolean l2 = (boolean) o2.get("isDir");
            return l2.compareTo(l1);
        });
        rs.put("code", 200);
        rs.put("msg", "查询成功");
        rs.put("data", dataList);
        return rs;
    }

    /**
     * 删除
     */
    @ResponseBody
    @RequestMapping("/file/del")
    public Map del(String file) {
        String root = properties.getRoot();
        if (root == null) {
            root = "/";
        }
        if (!root.endsWith("/")) {
            root += "/";
        }
        if (file != null && !file.isEmpty()) {
            File f = new File(File.listRoots()[0], root + file);
            if (f.delete()) {
                File smF = new File(File.listRoots()[0], root + "sm/" + file);
                smF.delete();
                return FileUtils.getRS(200, "删除成功");
            }
        }
        return FileUtils.getRS(500, "删除失败");
    }
}